package com.yang.mall.tools;

/**
 * Created by chijr on 16/11/5.
 */

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.SimpleDateFormatSerializer;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
//import sun.misc.BASE64Encoder;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.math.BigDecimal;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

public class Utils {


    private static SerializeConfig mapping = new SerializeConfig();
    private static String dateFormat;

    static {
        dateFormat = "yyyy-MM-dd HH:mm:ss";
        mapping.put(Date.class, new SimpleDateFormatSerializer(dateFormat));
    }


    public Utils() {


    }

    public static Date getDateZero(Date dt){

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(dt);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        Date zero = calendar.getTime();
        return zero;

    }


    public static Date dateAddDay(Date dt,int d){

        Calendar c = Calendar.getInstance();
        c.setTime(new Date());
        c.add(Calendar.DAY_OF_MONTH, d);
        return c.getTime();

    }

//    public static String encodePassword(String password){
//
//       return MD5.md5(password+JWTUtils.base64Secret);
//
//    }

    public static int parseInt(String intString) {



        intString = StringUtils.trim(intString);

        if (StringUtils.isEmpty(intString)) {

            return 0;
        }

        int value = 0;

        try {
            value = Integer.parseInt(intString);
        } catch (Exception e) {

            System.err.println("字符串转换数据出错：原始数据是:"+intString+" 出错原因："
                    +e.getMessage());

            return value;

        }


        return value;


    }


    public static double parseDouble(String doubleString) {

        if (StringUtils.isEmpty(doubleString)) {

            return 0.0;
        }


        double value = 0.0;

        try {


            value = Double.parseDouble(doubleString);
        } catch (Exception e) {

            return value;

        }

        return value;


    }


    public static String mapToUrl(String baseUrl, Map<String, String> newParams) {

        MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();

        params.setAll(newParams);


        UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(baseUrl).queryParams(params).build();

        return uriComponents.toString();


    }


    //get request headers
    public static Map<String, String> getHeaders(HttpServletRequest request) {

        Map<String, String> map = new HashMap<String, String>();

        Enumeration headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = (String) headerNames.nextElement();
            String value = request.getHeader(key);
            map.put(key, value);
        }

        return map;
    }

    public static String safeString(String filePath) {
        if (StringUtils.isEmpty(filePath)) {
            return "";
        }

        return filePath;

    }

    public static String safeStringArray(String[] array, int pos) {

        if (array == null) {
            return "";
        }

        if ((array.length - 1) < pos) {

            return "";

        }

        return StringUtils.trim(array[pos]);

    }


    public static List<String> readLines(String filePath) {


        ArrayList<String> strs = new ArrayList<String>();
        BufferedReader br = null;
        String temp = "";

        try {
            br = new BufferedReader(new FileReader(filePath));
            while ((temp = br.readLine()) != null) {
                System.out.println(temp);
                strs.add(temp);
            }

        } catch (FileNotFoundException e1) {
            System.out.println("指定的文件不存在");
        } catch (IOException e2) {
            e2.printStackTrace();
        } finally {
            try {
                if (br != null) {
                    br.close();
                    br = null;
                }
                return strs;

            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }
    }



    public static String readString(String filePath) throws IOException

    {


            File file=new File(filePath);

            FileInputStream inStream=new FileInputStream(file);


            ByteArrayOutputStream bos = new ByteArrayOutputStream();

            byte[] buffer=new byte[1024];

            int length=-1;

            length = inStream.read(buffer);
            while(length!=-1) {

                bos.write(buffer,0,length);


                length = inStream.read(buffer);


                // .write方法 SDK 的解释是 Writes count bytes from the byte array buffer starting at offset index to this stream.

                //  当流关闭以后内容依然存在

            }

            try {
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                inStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

            return bos.toString();

            // 为什么不一次性把buffer得大小取出来呢？为什么还要写入到bos中呢？ return new(buffer,"UTF-8") 不更好么?

            // return new String(bos.toByteArray(),"UTF-8");



    }
    public static String excptionStackToString(Exception e){

        StringWriter sw = null;
        PrintWriter pw = null;
        try {
            sw = new StringWriter();
            pw =  new PrintWriter(sw);
            //将出错的栈信息输出到printWriter中
            e.printStackTrace(pw);
            pw.flush();
            sw.flush();
        } finally {
            if (sw != null) {
                try {
                    sw.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            if (pw != null) {
                pw.close();
            }
        }

        return pw.toString();

    }

    public static String formatDateTime(Date dt) {

        String tmstr = String.format("%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS", dt);
        return tmstr;


    }


    public static String timeString(Date date)
    {
        SimpleDateFormat sdf=new SimpleDateFormat("HH:mm");
        return sdf.format(date);
    }
    public static String totalTimeString(Date date)
    {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        return sdf.format(date);
    }

    public  static  Date addDay(Date day ,int many){
        Calendar ca = Calendar.getInstance();
        ca.setTime(day);
        ca.add(Calendar.DATE, many);
        day = ca.getTime();
        return day;
    }


    public static String getHashMD5(String source){

        return Utils.getHash(source,"MD5");
    }

    public static String getHashSHA(String source){

        return Utils.getHash(source,"SHA");
    }


    /**
     * 由于MD5 与SHA-1均是从MD4 发展而来，它们的结构和强度等特性有很多相似之处
     * SHA-1与MD5 的最大区别在于其摘要比MD5 摘要长 32 比特（1byte=8bit，相当于长4byte，转换16进制后比MD5多8个字符）。
     * 对于强行攻击，：MD5 是2128 数量级的操作，SHA-1 是2160数量级的操作。
     * 对于相同摘要的两个报文的难度：MD5是 264 是数量级的操作，SHA-1 是280 数量级的操作。
     * 因而，SHA-1 对强行攻击的强度更大。 但由于SHA-1 的循环步骤比MD5 多（80:64）且要处理的缓存大（160 比特:128 比特），SHA-1 的运行速度比MD5 慢。
     *
     * @param source 需要加密的字符串
     * @param hashType 加密类型 （MD5 和 SHA）
     * @return
     */

    public static String getHash(String source, String hashType) {
        // 用来将字节转换成 16 进制表示的字符
        char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

        try {
            MessageDigest md = MessageDigest.getInstance(hashType);
            md.update(source.getBytes()); // 通过使用 update 方法处理数据,使指定的 byte数组更新摘要
            byte[] encryptStr = md.digest(); // 获得密文完成哈希计算,产生128 位的长整数
            char str[] = new char[16 * 2]; // 每个字节用 16 进制表示的话，使用两个字符
            int k = 0; // 表示转换结果中对应的字符位置
            for (int i = 0; i < 16; i++) { // 从第一个字节开始，对每一个字节,转换成 16 进制字符的转换
                byte byte0 = encryptStr[i]; // 取第 i 个字节
                str[k++] = hexDigits[byte0 >>> 4 & 0xf]; // 取字节中高 4 位的数字转换, >>> 为逻辑右移，将符号位一起右移
                str[k++] = hexDigits[byte0 & 0xf]; // 取字节中低 4 位的数字转换
            }
            return new String(str); // 换后的结果转换为字符串
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 返回http请求URL
     * @param request
     * @return
     */
    public static String getRequstMethodAndURLAndParams(HttpServletRequest request,String userId){
        if(request.getQueryString() != null){
            return request.getMethod() + " " + request.getRequestURL() + "?" + request.getQueryString();
        }

        return request.getMethod() + " " + request.getRequestURL().toString()+" userId:"+userId;
    }


    /**
     * 返回http请求URL
     * @param request
     * @return
     */
    public static String getRequstUrl(HttpServletRequest request){
        if(request.getQueryString() != null){
            return request.getMethod() + " " + request.getRequestURL() + "?" + request.getQueryString();
        }

        return request.getMethod() + " " + request.getRequestURL().toString();
    }

    public static String getId() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "ID" + id;

    }


    public static String getParkingRecordId() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "PR" + id;

    }

    public static String getWithdrawId() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "WD" + id;

    }


    public static String getChatReplyId() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "CR" + id;

    }

    public static String getElectronicCardId() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "EC" + id;

    }



    public static String getChatId() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "C" + id;

    }

    public static String getPushId() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "P" + id;

    }

    public static String getCarIn() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "CI" + id;

    }

    public static String getGroupId() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "G" + id;

    }
    public static String getGroupDetailId() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "GD" + id;

    }


    public static String getCollectId() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "C" + id;

    }




    public static String getAmountId() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "A" + id;

    }

    public static String getCarPark() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "CP" + id;

    }

    public static String getBannerId() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "B" + id;

    }

    public static String getPrepareId() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "P" + id;

    }

    public static String getPayId() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "P" + id;

    }

    public static String getShareApplyId() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "SA" + id;

    }



    public static String getUserId() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "U" + id;
    }

    public static String getWalletId() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "W" + id;

    }



    public static String getAppointId() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "A" + id;

    }

    public static String getOrderId() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "O" + id;

    }

    public static String getRecordId() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "R" + id;

    }



    public static String getCarId() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "C" + id;

    }



    public  static String getPassword(){

        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "Pw" + id;

    }


    public static int getInt(Object o) {


        if (o == null) {
            return 0;
        }

        if (o instanceof Integer) {
            Integer i = (Integer) o;
            return i.intValue();
        }

        if (o instanceof BigDecimal) {
            BigDecimal b = (BigDecimal) o;
            return b.intValue();
        }

        if (o instanceof Long) {
            Long b = (Long) o;
            return b.intValue();
        }

        if (o instanceof Float) {
            Float b = (Float) o;
            return b.intValue();
        }

        if (o instanceof Double) {
            Double b = (Double) o;
            return b.intValue();
        }

        return 0;


    }

//    public static String md5(String str) {
//        String newstr = null;
//        try {
//            MessageDigest md5 = MessageDigest.getInstance("MD5");
//
//            BASE64Encoder base64en = new BASE64Encoder();
//            //加密后的字符串
//            newstr = base64en.encode(md5.digest(str.getBytes("utf-8")));
//        } catch (Exception e) {
//
//        }
//        return newstr;
//    }

    public static String getString(Map m, String key) {

        Object o = m.get(key);

        if (o == null) {
            return null;
        }

        return String.valueOf(o);

    }


    public static String objectToString(Object objectInstance){


        JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

        String str = JSON.toJSONString(objectInstance, SerializerFeature.WriteDateUseDateFormat);


        return str;



    }


    public static HashMap<String,Object> objectToMap(Object objectInstance){


        JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

        String str = JSON.toJSONString(objectInstance, SerializerFeature.WriteDateUseDateFormat);


        HashMap<String, Object> map = JSON.parseObject(str, new TypeReference<HashMap<String, Object>>(){});

        return map;



    }

    //生成取餐码
    public static  int getTackCode(Date date) {
        return 1;
    }



    public static ObjectMapper getObjectMap(){

        ObjectMapper mapper = new ObjectMapper();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        mapper.setDateFormat(format);
        return mapper;

    }


    public static String objectToJsonString(Object o){

        try {
            String outJson = Utils.getObjectMap().writeValueAsString(o);
            return outJson;
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return "";
        }



    }

    public static  HashMap<String, Object> stringToMap(String  content){

        JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

        HashMap<String, Object> map = JSON.parseObject(content, new TypeReference<HashMap<String, Object>>(){});

        return map;





    }


    public static  Object stringToObject(String  content){

        JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

        Object obj = JSON.parse(content);

        return obj;



    }




    public static int getInt(Map m, String key) {

        Object o = m.get(key);

        if (o == null) {
            return 0;
        }

        if (o instanceof Integer) {
            Integer i = (Integer) o;
            return i.intValue();
        }

        if (o instanceof BigDecimal) {
            BigDecimal b = (BigDecimal) o;
            return b.intValue();
        }

        if (o instanceof Long) {
            Long b = (Long) o;
            return b.intValue();
        }

        if (o instanceof Float) {
            Float b = (Float) o;
            return b.intValue();
        }

        if (o instanceof Double) {
            Double b = (Double) o;
            return b.intValue();
        }

        return 0;


    }


    public static String file2String(File file, String encoding) {
        InputStreamReader reader = null;
        StringWriter writer = new StringWriter();
        try {
            if (encoding == null || "".equals(encoding.trim())) {
                reader = new InputStreamReader(new FileInputStream(file), encoding);
            } else {
                reader = new InputStreamReader(new FileInputStream(file));
            }
            //将输入流写入输出流
            char[] buffer = new char[10*1024];
            int n = 0;
            while (-1 != (n = reader.read(buffer))) {
                writer.write(buffer, 0, n);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            if (reader != null)
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
        //返回转换结果
        if (writer != null)
            return writer.toString();
        else return null;
    }



    public static String convertStreamToString(InputStream is) {
        /*
          * To convert the InputStream to String we use the BufferedReader.readLine()
          * method. We iterate until the BufferedReader return null which means
          * there's no more data to read. Each line will appended to a StringBuilder
          * and returned as String.
          */
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();

        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return sb.toString();
    }

    public static String getStoreId() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "store" + id;
    }

    public static Date strToDate(String str){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = simpleDateFormat.parse(str);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }


    /**
     * 判断当前时间是否在时间段内
     * @param beginStr
     * @param endStr
     * @return
     */
    public static boolean belongTime(String beginStr, String endStr) {
        try {
            SimpleDateFormat df = new SimpleDateFormat("HH:mm");//设置日期格式
            Date now =null;
            Date beginTime = null;
            Date endTime = null;
            //设置当前时间
            now = df.parse(df.format(new Date()));
            Calendar date = Calendar.getInstance();
            date.setTime(now);

            //设置起始时间
            beginTime = df.parse(beginStr);
            Calendar begin = Calendar.getInstance();
            begin.setTime(beginTime);

            //设置终止时间
            endTime = df.parse(endStr);
            Calendar end = Calendar.getInstance();
            end.setTime(endTime);

            if (date.after(begin) && date.before(end)) {
                System.out.println("----------时间判断返回：true");
                return true;
            } else {
                System.out.println("----------时间判断返回：false");
                return false;
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        System.out.println("----------时间判断返回：false");
        return  false;
    }

    public static Date strToDateTime(String str){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = null;
        try {
            date = simpleDateFormat.parse(str);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    public static String dateToStr(Date date){
        SimpleDateFormat sdf =   new SimpleDateFormat( "yyyy年MM月dd日 HH时mm分" );
        String str = sdf.format(date);
        return str;
    }


    public static  boolean belongCalendar(String from,String to){
        Calendar now = Calendar.getInstance();
        now.setTime(new Date());//当前时间

        //转换起始时间
        Calendar after = Calendar.getInstance();
        after.setTime(strToDate(from));

        //转换终止时间
        Calendar before = Calendar.getInstance();
        before.setTime(strToDate(to));

        if (now.after(after) && now.before(before)) {
            return true;
        } else {
            return false;
        }

    }

    /**
     * 中国正常GCJ02坐标---->百度地图BD09坐标
     * @param gg_lat
     * @param gg_lon
     * @return
     */
    public static Map Convert_GCJ02_To_BD09(double gg_lon, double gg_lat){
        double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
        double x = gg_lon, y = gg_lat;
        double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
        double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);
        double bd_lon = z * Math.cos(theta) + 0.0065;
        double bd_lat = z * Math.sin(theta) + 0.006;
        Map map = new HashMap();
        map.put("gg_lon",bd_lon);
        map.put("gg_lat",bd_lat);

        return map;
    };

    /**
     *百度地图BD09坐标---->中国正常GCJ02坐标
     * @param gg_lat
     * @param gg_lon
     * @return
     */
    public static Map Convert_BD09_To_GCJ02(double gg_lon, double gg_lat){
        double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
        double x = gg_lon -0.0065, y = gg_lat-0.006;
        double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
        double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
        double bd_lon = z * Math.cos(theta);
        double bd_lat = z * Math.sin(theta)  ;
        Map map = new HashMap();
        map.put("gg_lat",bd_lat);
        map.put("gg_lon",bd_lon);
        return map;
    };

    public static String decodeUnicode(String theString) {
        char aChar;
        int len = theString.length();
        StringBuffer outBuffer = new StringBuffer(len);
        for (int x = 0; x < len;) {
            aChar = theString.charAt(x++);
            if (aChar == '\\') {
                aChar = theString.charAt(x++);
                if (aChar == 'u') {
                    // Read the xxxx
                    int value = 0;
                    for (int i = 0; i < 4; i++) {
                        aChar = theString.charAt(x++);
                        switch (aChar) {
                            case '0':
                            case '1':
                            case '2':
                            case '3':
                            case '4':
                            case '5':
                            case '6':
                            case '7':
                            case '8':
                            case '9':
                                value = (value << 4) + aChar - '0';
                                break;
                            case 'a':
                            case 'b':
                            case 'c':
                            case 'd':
                            case 'e':
                            case 'f':
                                value = (value << 4) + 10 + aChar - 'a';
                                break;
                            case 'A':
                            case 'B':
                            case 'C':
                            case 'D':
                            case 'E':
                            case 'F':
                                value = (value << 4) + 10 + aChar - 'A';
                                break;
                            default:
                                throw new IllegalArgumentException(
                                        "Malformed   \\uxxxx   encoding.");
                        }

                    }
                    outBuffer.append((char) value);
                } else {
                    if (aChar == 't')
                        aChar = '\t';
                    else if (aChar == 'r')
                        aChar = '\r';
                    else if (aChar == 'n')
                        aChar = '\n';
                    else if (aChar == 'f')
                        aChar = '\f';
                    outBuffer.append(aChar);
                }
            } else
                outBuffer.append(aChar);
        }
        return outBuffer.toString().replace("\\","");
    }


    public static String nullToString(Object obj){
        if(null == obj){
            return "";
        }else{
            return obj.toString();
        }
    }

    public static String getHomeResId() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "Hres" + id;
    }
    public static String getHomeStr() {
        ObjectId objId = ObjectId.get();
        String id = objId.toString();
        return "Hstr" + id;
    }


    public static String getServerDomain(HttpServletRequest request){
        if(request == null){
            return null;
        }
//        String url = request.getRequestURL().toString();
//        int pos = url.lastIndexOf("/");
//        if(pos != -1) {
//            url = url.substring(0, pos);
//        }

        String url = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort();
        return url;
    }
}
